package sky.cin.framework.sfoc.advanced.mvc;

import sky.cin.framework.log.Croog;
import sky.cin.framework.sfoc.advanced.mvc.annotations.ApiDescribe;
import sky.cin.framework.sfoc.core.annotations.beans.Component;
import sky.cin.framework.sfoc.core.annotations.beans.Controller;
import sky.cin.framework.sfoc.core.annotations.https.GetMapping;
import sky.cin.framework.sfoc.core.annotations.https.RequestMapping;
import sky.cin.framework.sfoc.core.annotations.https.UrlMapping;
import sky.cin.framework.sfoc.core.common.utils.BeanUtils;
import sky.cin.framework.sfoc.core.interfaces.BeanCreator;
import sky.cin.framework.sfoc.core.interfaces.BeanDefinition;

import java.lang.reflect.Method;
import java.util.Arrays;

@Component
public class ControllerCreator implements BeanCreator {
    
    private final Croog log = new Croog("sky.cin.framework.sfoc.advanced.mvc.ControllerCreator");
    
    public Object doCreateBean(String beanName, BeanDefinition definition, Object bean) {
        if (BeanUtils.isAnnotationPresent(definition.getClazz(), Controller.class)) {
            bean = resolveControllers(bean, beanName, definition.getClazz());
        }
        return bean;
    }
    
    private Object resolveControllers(Object bean, String beanName, Class<?> clazz) {
        // 获取类对应的 url 路径
        RequestMapping requestMapping = BeanUtils.getAnnotation(clazz, RequestMapping.class);
        String classMapping = requestMapping == null ? "" : requestMapping.value();
        Method[] methods = clazz.getDeclaredMethods();
        // 遍历所有方法
        Arrays.stream(methods)
                .filter(method -> BeanUtils.isAnnotationPresent(method, UrlMapping.class))
                .forEach(method -> resolveController(bean, clazz, classMapping, method));
        return null;
    }

    private void resolveController(Object bean, Class<?> clazz, String classMapping, Method method) {
        String methodMapping = classMapping + BeanUtils.getAnnotation(method, GetMapping.class).value();
        DispatcherServlet.put(methodMapping, new RequestHandler(method, bean));
        printLog(clazz, method, methodMapping);
    }
    
    private void printLog(Class<?> clazz, Method method, String methodMapping) {
        Class<?>[] parameterTypes = method.getParameterTypes();
        String[] paramTypes = new String[parameterTypes.length];
        for (int index = 0; index < parameterTypes.length; index++) {
            paramTypes[index] = parameterTypes[index].getSimpleName();
        }
        String params = Arrays.toString(paramTypes);
        String methodFormat = String.format("%s.%s(%s): %s",
            clazz.getSimpleName(),
            method.getName(),
            params.substring(1, params.length() - 1),
            method.getReturnType().getSimpleName()
        );
        String msg = String.format("[GET] %s => %s", methodMapping, methodFormat);
        ApiDescribe apiDescribeAnno = BeanUtils.getAnnotation(method, ApiDescribe.class);
        if (apiDescribeAnno != null) {
            msg += " " + apiDescribeAnno.value();
        }
        log.info(msg);
    }
    
}
